use log::info;
// use tauri::{AppHandle,Manager};
// use chrono::{Utc, NaiveDateTime};
use std::collections::HashMap;
use sysinfo::System;

#[path ="../util/http.rs"]
mod http;
#[path ="../util/crypt_util.rs"]
mod crypt_util;
#[path ="../util/data_util.rs"]
mod data_util;

#[path ="../util/file.rs"]
mod file;

#[cfg(test)]
mod tests {
    use super::*;
    use tokio::runtime::Runtime;
    #[test]
    fn it_work(){
        // utils::log_config::init_log_config();
        let rt = Runtime::new().unwrap();
        // let app = tauri::Builder::default()
        //         .build(tauri::generate_context!())
        //         .expect("error while building tauri application");

        let _rst = rt.block_on(yzg_login("94330265","94330265",Some("mobile"),None));
    }
    #[test]
    fn get_mac(){
        // utils::log_config::init_log_config(); 、、 94330265  pc0087003736
        let rt = Runtime::new().unwrap(); // 653c51761ab1d7ef01  
        let rst = rt.block_on(pre_login_mac("pc0087003736",Some("Pc"),None));
        println!("{:?}",rst);
        info!("{:?}",rst);
    }
}
pub fn get_mac()->String{
    let mut mac = String::new();
    match mac_address2::get_mac_address() {
        Ok(Some(ma)) => {
            mac = ma.to_string()
        }
        Ok(None) => println!("No MAC address found."),
        Err(e) => println!("{:?}", e),
    }
    mac
}

pub fn uuid()->String{
    let uuid = uuid::Uuid::new_v4();
    let rand32b = uuid.simple().to_string().to_uppercase();
    rand32b
}
// const DATE_TIME_FMT:&str = "%Y-%m-%d %H:%M:%S";
pub async fn yzg_login(user_name: &str,pwd:&str,term:Option<&str>,app_data_path:Option<String>) -> anyhow::Result<String,anyhow::Error>{
    let org_code = user_name;//"pc0087003736";
    // 验证配置
    // let valid = get_remote_config(org_code).await;
    // if !valid {
    //     return Err(anyhow::Error::msg("配置错误"));
    // }
    let m_a =  pre_login_mac(org_code,term,app_data_path).await;
    let r_mac;
    if let Ok(mm) = m_a {
        r_mac = mm;
    }else{
        r_mac = "".to_string();
    }
    let mac = get_mac();
    let mut params = HashMap::new();
    if r_mac.is_empty() {
        params.insert("localMac", mac.as_str());
    }else {
        params.insert("localMac", r_mac.as_str());
    }
    // let sys = sysinfo::System::new_all();
    // let mem_bytes = sys.total_memory();
    
    let sys_name = System::name();
    let kernel_version = System::kernel_version();
    let os_version = System::os_version();
    println!("kernel_version {:?} sys_name {:?} os_version {:?}",kernel_version,sys_name,os_version);
    // let device_id;
    // if let Some(k_v) = kernel_version {
    //     device_id = k_v.as_str();
    // }else{
    //     device_id = "";
    // }
    let device_version;
    let kv;
    if let Some(k_v) = os_version {
        kv = k_v;
        device_version = kv.as_str();
    }else{
        device_version = "";
    }
    let os;
    let kv;
    if let Some(k_v) = sys_name {
        kv = k_v;
        os = kv.as_str();
    }else{
        os = "";
    }
    let mut hard_info = "deviceId=".to_string();
    hard_info += mac.as_str();
    let os_name;
    let uuid = uuid();
    let crypt_pwd ;
    if let Some(t) = term{
        if t == "mobile"{
            crypt_pwd = crypt_util::get_encode_param(pwd,uuid.clone());
            hard_info += ",deviceType=android";
            os_name = "android";
        }else {
            crypt_pwd = crypt_util::encrypt_pwd(pwd,uuid.clone());
            os_name = os;
        }
        
    }else{
        crypt_pwd = crypt_util::encrypt_pwd(pwd,uuid.clone());
        os_name = os;
    }

    hard_info += ",versionCode=";
    hard_info += device_version;
    hard_info += ",markId=000,deviceModel=";
    hard_info += os_name;
    hard_info += ",deviceVersion_Release=";
    hard_info += device_version;
    hard_info += ",screenResolution=1920*1024";
    
    params.insert("encryptToken", uuid.as_str());
    params.insert("loginAccount", user_name);
    params.insert("deviceId", &mac);
    params.insert("deviceInfo", user_name);
    params.insert("hardInfo", hard_info.as_str());
    params.insert("pwd", crypt_pwd.as_str());
    // params.insert("ip", pwd.as_str());
    
    info!(">>>>>>>>>>>>>>>>>>..login params {:?} r_mac {}",params,r_mac);
    let url = "https://vps-api.ule.com/yzglogin/stationLogin";
    let local_mac = params.get("localMac").copied();
    let res = http::fetch(url, "form",Some(params), None,false,local_mac,term).await;
    // println!("login result {:?}",res);
    let resp_str;
    match res {
        Err(e) => {
            return anyhow::Result::Err(e.into());
        },
        Ok(resp)=>{
            resp_str = resp.clone();
        }
    }
    Ok(resp_str)
}

pub async fn pre_login_mac(org_code: &str,term:Option<&str>,app_data_path:Option<String>) -> anyhow::Result<String,anyhow::Error> {
    let file_name = crypt_util::encrypt_pwd("mac_info", "&%JKwsxedcasdf(*&%JKsmloolkigr(*".to_string());
    let file_path;
    if let Some(p)=app_data_path{
        file_path = p;
    }else{
        file_path = "".to_string();
    }
    let full_path = file_path.to_string()+file_name.as_str() + ".txt";
    println!("full_path {}",full_path);
    // get from file
    let lines = file::read_lines_from_file(full_path.as_str());
    // println!("pre_login_mac lines {:?}",lines);
    // info!("pre_login_mac lines {:?}",lines);
    let mut mm = String::new();
    let time = std::time::SystemTime::now();
    let milliseconds ;
    if let Ok(duration) = time.duration_since(SystemTime::UNIX_EPOCH) {
        milliseconds = duration.as_millis(); // 转换为毫秒数
    } else {
        milliseconds = 1;
    }
    match lines {
        Ok(l) => {
            for line in l {
                // let line = line.unwrap();
                let s: Vec<&str> = line.split(">>>>>>").collect();
                if s.len() == 1 {
                    continue;
                }
                let time_s = s.get(0).copied();
                if let Some(t) = time_s {
                    let tt = t.parse::<u128>();
                    if let Ok(ttt) = tt {
                        // 7日内有效
                        if milliseconds-ttt > 7*86400000 {
                            continue;
                        }
                    }
                }
                let line_data = s.get(1).copied().unwrap();
                let v = crypt_util::decrypt_pwd(line_data, "&%JKsmloljasdf(*&%JKsmloljasdf(*".to_string());
                let json_val: serde_json::Value = serde_json::from_str(v.as_str()).unwrap();
                // info!("pre_login_mac json_val {:?}",json_val);
                if let Some(v) = json_val.get("villageNo") {
                    // info!("pre_login_mac json_val {:?}",v);
                    if v != org_code {
                        continue;
                    }
                }
                if let Some(m) = json_val.get("mac") {
                    mm = m.as_str().unwrap().to_string();
                }
                if let Some(term) = json_val.get("createUser") {
                    if term.to_string().contains("android") {
                        // info!("pre_login_mac term {:?}",term.to_string());
                        if let Some(m) = json_val.get("mac") {
                            mm = m.as_str().unwrap().to_string();
                            break;
                        }
                    }
                }
            }
            if !mm.is_empty() {
                // info!("get mac from file {:?}",mm);
                return Ok(mm);
            }
        },
        Err(_) => {
            // return anyhow::Result::Err(e.into());
        }
    }
    let mut tt = "Pc" ;
    if let Some(t) = term {
        if  t == "mobile" {
            tt = "App";
        }
    }
    
    // info!("get user prelogin mac");
    let get_mac_url = String::from("https://vps-api.ule.com/yzglogin/safety/getDeviceList?orgCode=") + org_code+"&loginChannel="+tt;
    let res = http::fetch(get_mac_url.as_str(),"form", None, None,false,None,None).await;
    println!("get mac res {:?} org_code {}",res,org_code);
    // info!("get mac res {:?} org_code {}",res,org_code);
    match res {
        Err(e) => {
            return anyhow::Result::Err(e.into());
        },
        Ok(resp) => {
            let json_val: serde_json::Value = serde_json::from_str(&resp).unwrap();
            if let Some(code) = json_val.get("code") {
                if "0000" == code {
                    let data = json_val.get("data");
                    if let Some(d) = data {
                        let arr = d.as_array().unwrap();
                        // info!("mac {:?}",arr);
                        let mut mm = String::new();
                        let mut mm2 = String::new();
                        for a in arr.iter() {
                            let aa = a.as_object();
                            // info!("aaaaa {:?}",aa);
                            if let Some(v) = aa {
                                let line_data = crypt_util::encrypt_pwd(serde_json::to_string(v).unwrap().as_str(), "&%JKsmloljasdf(*&%JKsmloljasdf(*".to_string());
                                // 当前时间
                                let time = std::time::SystemTime::now();
                                let milliseconds ;
                                if let Ok(duration) = time.duration_since(SystemTime::UNIX_EPOCH) {
                                    milliseconds = duration.as_millis(); // 转换为毫秒数
                                } else {
                                    milliseconds = 1;
                                }
                                let _ = file::append_string_to_file(full_path.as_str(), (milliseconds.to_string()+">>>>>>"+line_data.as_str() + "\n").as_str());
                                let mac = v.get("mac").unwrap().as_str().unwrap();
                                let ip = v.get("ip").unwrap().as_str().unwrap();
                                println!("fff {} {} {}", mac, ip,mm);
                                if mm.is_empty() {
                                    mm = mac.to_string();
                                }
                                if mm2.is_empty() {
                                    if let Some(term) = json_val.get("createUser") {
                                        if term.to_string().contains("android") {
                                            info!("pre_login_mac term {:?}",term.to_string());
                                            if let Some(m) = json_val.get("mac") {
                                                mm2 = m.as_str().unwrap().to_string();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if mm2.is_empty() {
                            return Ok(mm);
                        }
                        return Ok(mm2);
                    }
                } else {
                    info!("api request error code {}", code);
                    // println!("api request error code {}", code);
                }
            }
            return Ok("".to_string());
        }
    }
}

pub async fn get_pre_login_mac(org_code: &str,term: &str) -> anyhow::Result<String,anyhow::Error> {
    
    let get_mac_url = String::from("https://vps-api.ule.com/yzglogin/safety/getDeviceList?orgCode=") + org_code+"&loginChannel="+term;
    let res = http::fetch(get_mac_url.as_str(),"form", None, None,false,None,None).await;
    // println!("get mac res {:?} org_code {}",res,org_code);
    info!("=============================get get_pre_login_mac res {:?} org_code {}",res,org_code);
    match res {
        Err(e) => {
            return anyhow::Result::Err(e.into());
        },
        Ok(resp) => {
            return Ok(resp);
        }
    }
}

use std::time::SystemTime;

pub async fn get_remote_config(org_code: &str) -> bool{
    let res = http::fetch("https://vps-api.ule.com/app/sysTime", "get", None, None,true,None,None).await;
    let curr_timestamp = match res {
        Err(_) => {
            let now = SystemTime::now(); // 获取当前系统时间

            if let Ok(duration) = now.duration_since(SystemTime::UNIX_EPOCH) {
                let milliseconds:u128 = duration.as_millis(); // 转换为毫秒数
                milliseconds
            } else {
                1
            }
        },
        Ok(str) => {
            let a = str.parse::<u128>().unwrap() ;
            a
        }
    };
    // info!("get_remote_config curr_timestamp {:?}",curr_timestamp);
    // get user prelogin mac
    let config_url = "https://gitee.com/api/v5/repos/new-fire-works/newfiredoc/raw/src%2Frecords.json?access_token=cdfdbbaf6b9ab6bfa95b11812fa9f063";
    let res = http::fetch(config_url, "get", None, None,true,None,None).await;
    let valid = match res {
        Err(_) => {
            return false;
        },
        Ok(str)=>{
            let json_arr: serde_json::Value = serde_json::from_str(str.as_str()).unwrap();
            // info!("remote config {:?}",json_arr);
            let arr = json_arr.as_array().unwrap();
            let mut valid_flag = false;
            for a in arr.iter() {
                let aa = a.as_object();
                if let Some(v) = aa {
                    let code = v.get("code").unwrap().as_str().unwrap();
                    if code != org_code  {
                        continue;
                    }
                    let status = v.get("status").unwrap().as_str().unwrap();
                    if status != "0" {
                        continue;
                    }
                    let end_time = v.get("endTime").unwrap().as_str().unwrap();
                    if !end_time.is_empty() {
                        let c_time = end_time.parse::<u128>().unwrap();
                        if curr_timestamp <= c_time {
                            valid_flag = true;
                        }
                    }else {
                        valid_flag = true;
                    }
                    // let proxy = v.get("proxy").unwrap().as_str().unwrap();
                    // let proxy_url = v.get("proxyUrl").unwrap().as_str().unwrap();
                    // println!("fff {} {}", mac, ip);
                }
            }
            valid_flag
        }
    };
    // info!("get_remote_config valid {:?}",valid);
    // println!("get_remote_config valid {:?}",valid);
    valid
}